using System;
using System.Collections;
using System.Threading;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using needle.UI.Controls.Flat.Windows.Forms.Helpers;
using needle.UI.Controls.Flat.Utilities.Drawing;

namespace needle.UI.Controls.Flat.Windows.Forms
{
	[DefaultEvent("ButtonPressed"),
	System.ComponentModel.ToolboxItem(true)]
	public class ButtonEdit : ControlBase, IFlashabledControl
	{
		private System.ComponentModel.IContainer components = null;
		private int m_ButtonWidth = 15;
		private bool m_ReadOnly = false;
		private bool m_AcceptsPlussKey = true;
		private bool m_ShowErrorProvider = true;
		private Icon mButtonIcon = null;

		//Style Neo, default!!
		private Color m_TextColor = Color.Black;
		private Color m_EditDisabledColor = Color.FromArgb(238, 238, 225);
		private Color m_EditReadOnlyColor = Color.FromArgb(238, 238, 225);
		private Color m_EditFocusedColor = Color.White;
		private Color m_EditColor = Color.FromArgb(242, 242, 228);
		private Color m_NegativeNumberColor = Color.Black;
		private Color m_FlashColor = Color.FromArgb(170, 170, 221);
		private Color m_ButtonColor = Color.FromArgb(242, 242, 228);
		private Color m_ButtonHotColor = Color.FromArgb(231, 231, 214);
		private Color m_ButtonPressedColor = Color.FromArgb(222, 217, 207);
		private Color m_ButtonBorderColor = Color.FromArgb(222, 217, 207);
		private Color m_ButtonBorderHotColor = Color.FromArgb(222, 217, 207);

		protected bool mDroppedDown = false;
		protected TextBoxBase mpTextBox;
		
		[Category("Action")]
		public event ButtonPressedEventHandler ButtonPressed  = null;

		[Category("Behavior")]
		public event ErrorOcurredEventHandler ErrorOcurred = null;

		#region Constructors

		public ButtonEdit():base()
		{
			InitializeComponent();
			mpTextBox.LostFocus     += new System.EventHandler(this.m_pTextBox_OnLostFocus);
			mpTextBox.GotFocus      += new System.EventHandler(this.m_pTextBox_OnGotFocus);
			mpTextBox.NumberOcurred += new NumberOcurredEventHandler(this.m_pTextBox_NumberOcurred);
			mpTextBox.Width = this.Width - m_ButtonWidth - 7;

			mButtonIcon = GraphicsUtils.LoadIcon("etc.ico");
		}

		#endregion

		#region Dispose

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#endregion

		#region Component Designer generated code
		private void InitializeComponent()
		{
			this.mpTextBox = new needle.UI.Controls.Flat.Windows.Forms.TextBoxBase();
			this.SuspendLayout();
			// 
			// mpTextBox
			// 
			this.mpTextBox.Anchor = (System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right);
			this.mpTextBox.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(242)), ((System.Byte)(242)), ((System.Byte)(228)));
			this.mpTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
			this.mpTextBox.DecimalPlaces = 2;
			this.mpTextBox.DecMaxValue = 999999999;
			this.mpTextBox.DecMinValue = -999999999;
			this.mpTextBox.Location = new System.Drawing.Point(3, 2);
			this.mpTextBox.Mask = needle.UI.Controls.Flat.Windows.Forms.EditMask.Custom;
			this.mpTextBox.Name = "mpTextBox";
			this.mpTextBox.NotAcceptsChars = "";
			this.mpTextBox.Required = false;
			this.mpTextBox.Size = new System.Drawing.Size(86, 13);
			this.mpTextBox.TabIndex = 0;
			this.mpTextBox.Text = "";
			this.mpTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.mpTextBox_KeyDown);
			this.mpTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.mpTextBox_KeyPress);
			this.mpTextBox.ErrorOcurred += new needle.UI.Controls.Flat.Windows.Forms.ErrorOcurredEventHandler(this.MpTextBoxErrorOcurred);
			this.mpTextBox.KeyUp += new System.Windows.Forms.KeyEventHandler(this.mpTextBox_KeyUp);
			this.mpTextBox.NumberOcurred += new needle.UI.Controls.Flat.Windows.Forms.NumberOcurredEventHandler(this.m_pTextBox_NumberOcurred);
			this.mpTextBox.TextChanged += new System.EventHandler(this.m_pTextBox_TextChanged);
			// 
			// ButtonEdit
			// 
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.mpTextBox});
			this.Name = "ButtonEdit";
			this.Size = new System.Drawing.Size(118, 19);
			this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.EnterpriseButtonEdit_MouseMove);
			this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.EnterpriseButtonEdit_MouseDown);
			this.ResumeLayout(false);

		}
		#endregion

		#region Events handlers

		private void mpTextBox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
		{
			this.OnKeyUp(e);
		}

		private void mpTextBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
		{
			this.OnKeyDown(e);
		}

		private void mpTextBox_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
		{
			this.OnKeyPress(e);
		}
						
		private void m_pTextBox_OnGotFocus(object sender, System.EventArgs e)
		{
			this.BackColor = this.EditFocusedColor;	
			this.OnGotFocus(e);
		}

		private void m_pTextBox_OnLostFocus(object sender, System.EventArgs e)
		{
			if(!mDroppedDown)
			{
				bool mReadOnly = this.mpTextBox.ReadOnly;
				bool mEnabled = this.Enabled;
				this.BackColor = this.Style!=null? Style.InteliEditColor(mReadOnly,mEnabled):
					StyleGuide.InteliEditColor(this.mpTextBox.ReadOnly,this.Enabled,this.m_EditColor, this.m_EditReadOnlyColor, this.m_EditDisabledColor);
				this.OnLostFocus(e);
			}			
		}

		private void m_pTextBox_TextChanged(object sender, System.EventArgs e)
		{
			this.OnTextChanged(e);
		}

		private void EnterpriseButtonEdit_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			this.Invalidate(false);
		}

		private void EnterpriseButtonEdit_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if(IsMouseInButtonRect())
			{
				this.Invalidate(false);
			}
		}

		private void m_pTextBox_NumberOcurred(object sender, NumberOcurredEventArgs e)
		{
			e.NegativeNumberColor = this.NegativeNumberColor;
			e.PositiveNumberColor = this.TextColor;
		}

		protected void MpTextBoxErrorOcurred(object sender, ErrorOcurredEventArgs e)
		{
			if (e.Message.Length > 0)
			{
				if (this.ErrorOcurred != null)
				{
					ErrorOcurredEventArgs oArg = new ErrorOcurredEventArgs(e.Message);
					ErrorOcurred(this, oArg); 
				}
			}
			//
			if (this.ShowErrorProvider) 
				base.Errors.SetError(this, e.Message);
		}

		#endregion

		#region Overrides

		protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
		{	
			base.OnMouseUp(e);

			if(e.Button == MouseButtons.Left && IsMouseInButtonRect())
				this.OnButtonPressed(new EventArgs());
		}

		protected override void OnStyleChanged(object sender, StyleEventArgs args)
		{
			base.OnStyleChanged(sender, args);

			if (args.PropertyName == "FlashColor") {this.FlashColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "TextColor") {this.TextColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditColor") {this.EditColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditFocusedColor") {this.EditFocusedColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditReadOnlyColor") {this.EditReadOnlyColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditDisabledColor") {this.EditDisabledColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditButtonColor") {this.ButtonColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditButtonHotColor") {this.ButtonHotColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "EditButtonPressedColor") {this.ButtonPressedColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "NegativeNumberColor") {this.NegativeNumberColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "ButtonBorderColor") {this.BorderColor = (Color)args.PropertyValue;}
			else if (args.PropertyName == "ButtonBorderHotColor") {this.BorderHotColor = (Color)args.PropertyValue;}

			this.BackColor = this.Style!=null? Style.InteliEditColor(m_ReadOnly,this.Enabled):
				StyleGuide.InteliEditColor(this.mpTextBox.ReadOnly,this.Enabled,this.m_EditColor, this.m_EditReadOnlyColor, this.m_EditDisabledColor);

			this.Invalidate(true);
		}

		protected override void OnPlansOfColorsChanged(object sender, PlansOfColorsChangedEventArgs args)
		{
			base.OnPlansOfColorsChanged(sender, args);

			if (this.Style!=null)
			{
				this.FlashColor = this.Style.FlashColor;
				this.EditColor = this.Style.EditColor;
				this.EditFocusedColor = this.Style.EditFocusedColor;
				this.EditReadOnlyColor = this.Style.EditReadOnlyColor;
				this.EditDisabledColor = this.Style.EditDisabledColor;
				this.TextColor = this.Style.TextColor;
				this.ButtonColor = this.Style.EditButtonColor;
				this.ButtonHotColor = this.Style.EditButtonHotColor;
				this.ButtonPressedColor = this.Style.EditButtonPressedColor;
				this.NegativeNumberColor = this.Style.NegativeNumberColor;
				this.ButtonBorderColor = this.Style.BorderColor;
				this.ButtonBorderHotColor = this.Style.BorderHotColor;

				this.BackColor = this.Style!=null? Style.InteliEditColor(m_ReadOnly,this.Enabled):
					StyleGuide.InteliEditColor(this.mpTextBox.ReadOnly,this.Enabled,this.m_EditColor, this.m_EditReadOnlyColor, this.m_EditDisabledColor);
			}

			this.Invalidate(true);
		}

		protected override void DrawControl(Graphics g,bool hot)
		{
			Rectangle rectButton = GetButtonRect;
			
			bool border_hot = hot;
			
			GraphicsUtils.DrawBorder(g,base.BorderColor,base.BorderHotColor, this.ClientRectangle,border_hot);

			bool btn_hot     = (IsMouseInButtonRect() && hot) || mDroppedDown;
			bool btn_pressed = IsMouseInButtonRect() && Control.MouseButtons == MouseButtons.Left && hot;

			
			GraphicsUtils.DrawButton(g,this.m_ButtonColor,
				this.m_ButtonHotColor,
				this.m_ButtonPressedColor,
				this.m_ButtonBorderColor,
				this.m_ButtonBorderHotColor,rectButton,border_hot,btn_hot,btn_pressed);
			
			if(this.ButtonIcon != null)
			{				
				Rectangle rectI  = new Rectangle(rectButton.Left+1,rectButton.Top,rectButton.Width-1,rectButton.Height-1);
				DrawHelpers.DrawIcon(g,this.ButtonIcon,rectI,false,btn_pressed);
			}
		}

		protected override void OnEnterKeyPressed() 
		{
			base.OnEnterKeyPressed();

			this.OnKeyDown(new KeyEventArgs(Keys.Enter));
			this.OnKeyPress(new KeyPressEventArgs((char)13));
			this.OnButtonPressed(new EventArgs());
		}

		protected override void OnEnabledChanged(System.EventArgs e)
		{
			base.OnEnabledChanged(e);
			this.BackColor = this.Style!=null? this.Style.InteliEditColor(this.mpTextBox.ReadOnly,this.Enabled):
				StyleGuide.InteliEditColor(this.mpTextBox.ReadOnly,this.Enabled,this.m_EditColor, this.m_EditReadOnlyColor, this.m_EditDisabledColor);
		}

		#endregion

		#region Virtuals

		protected virtual void OnButtonPressed(EventArgs e) 
		{
			if(this.ButtonPressed != null && !this.mpTextBox.ReadOnly && this.Enabled)
				this.ButtonPressed(this, new System.EventArgs());
		}

		#endregion

		#region Internal helpers

		private void ThreadFlashControl()
		{
			for (int i=1; i<=8;i++)
			{
				if(this.mpTextBox.BackColor == this.EditColor)
				{
					this.mpTextBox.BackColor = this.FlashColor;
				}
				else
				{
					this.mpTextBox.BackColor = this.EditColor;
				}
				Thread.Sleep(150);
			}

			this.mpTextBox.BackColor = this.EditColor;
		}

		#endregion

		#region Methods

		protected bool IsMouseInButtonRect()
		{
			Rectangle rectButton = GetButtonRect;
			Point mPos = Control.MousePosition;
			if(rectButton.Contains(this.PointToClient(mPos)))
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		#endregion 

		#region Properties

		//2002-08-07 - GWO - Added to accept regular expressions.
		[Category("Behavior")]
		public string RegularExpression
		{
			get {return this.mpTextBox.RegularExpression;}
			set {this.mpTextBox.RegularExpression = value;}
		}

		//2002-08-24 - GWO - Added to accept custom messages.
		[Category("Behavior"),
		Localizable(true)]
		public string ErrorMessage
		{
			get {return mpTextBox.ErrorMessage;}
			set {mpTextBox.ErrorMessage = value;}
		}

		protected virtual Icon ButtonIcon
		{
			get{return this.mButtonIcon;}
		}

		[Browsable(false)]
		public Rectangle GetButtonRect
		{
			get 
			{
				Rectangle rectButton = new Rectangle(this.Width - m_ButtonWidth,1,m_ButtonWidth - 1,this.Height - 2);
				return rectButton;
			}
		}
		
		[Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public new Color BackColor
		{
			get{ return base.BackColor; }

			set
			{
				base.BackColor      = value;
				if (mpTextBox!=null) mpTextBox.BackColor = value;
			}
		}

		[Browsable(false)]
		public override Color ForeColor
		{
			get{ return base.ForeColor; }

			set
			{
				base.ForeColor       = value;
				mpTextBox.ForeColor = value;
			}
		}

		[Category("Style")]
		public Color TextColor
		{
			get {return m_TextColor;}
			set 
			{
				m_TextColor = value;
				this.mpTextBox.ForeColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color FlashColor
		{
			get {return m_FlashColor;}
			set 
			{
				m_FlashColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color EditColor
		{
			get {return m_EditColor;}
			set 
			{
				m_EditColor = value;
				this.BackColor = value;
				this.mpTextBox.BackColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color NegativeNumberColor
		{
			get {return m_NegativeNumberColor;}
			set 
			{
				m_NegativeNumberColor = value;
			}
		}

		[Category("Style")]
		public Color EditFocusedColor
		{
			get {return m_EditFocusedColor;}
			set 
			{
				m_EditFocusedColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color EditReadOnlyColor
		{
			get {return m_EditReadOnlyColor;}
			set 
			{
				m_EditReadOnlyColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color EditDisabledColor
		{
			get {return m_EditDisabledColor;}
			set 
			{
				m_EditDisabledColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color ButtonColor
		{
			get {return m_ButtonColor;}
			set 
			{
				m_ButtonColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color ButtonHotColor
		{
			get {return m_ButtonHotColor;}
			set 
			{
				m_ButtonHotColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color ButtonPressedColor
		{
			get {return m_ButtonPressedColor;}
			set 
			{
				m_ButtonPressedColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color ButtonBorderColor
		{
			get {return m_ButtonBorderColor;}
			set 
			{
				m_ButtonBorderColor = value;
				this.Invalidate();
			}
		}

		[Category("Style")]
		public Color ButtonBorderHotColor
		{
			get {return m_ButtonBorderHotColor;}
			set 
			{
				m_ButtonBorderHotColor = value;
				this.Invalidate();
			}
		}

		[Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public DateTime DateValue
		{
			get {return mpTextBox.DateValue;}
			set {mpTextBox.DateValue = value;}
		}

		[Category("Behavior")]
		public EditMask Mask
		{
			get {return mpTextBox.Mask;}
			set
			{
				mpTextBox.Mask = value;
			}
		}

		[Browsable(false)]
		public bool ValidWithMask
		{
			get{return mpTextBox.ValidWithMask;}
		}

		[Category("Behavior")]
		public bool AcceptsPlussKey
		{
			get {return m_AcceptsPlussKey;}
			set {m_AcceptsPlussKey = value;}
		}

		[Category("Behavior")]
		public bool ShowErrorProvider
		{
			get {return m_ShowErrorProvider;}
			set {m_ShowErrorProvider = value;}
		}

		[Category("Behavior")]
		public bool Required
		{
			get	{return mpTextBox.Required;}
			set	{mpTextBox.Required = value;}
		}

		[Category("Behavior")]
		public bool ReadOnly
		{
			get {return m_ReadOnly;}

			set 
			{
				m_ReadOnly = value;
				mpTextBox.ReadOnly = value;

				if(value)
				{
					this.BackColor = this.EditReadOnlyColor;
				}
				else
				{
					if(this.ContainsFocus)
					{
						this.BackColor = this.EditFocusedColor;
					}
					else
					{
						this.BackColor = this.EditColor;
					}
				}
			}
		}
		
		[Category("Behavior")]
		public int MaxLength
		{
			get {return mpTextBox.MaxLength;}
			set { mpTextBox.MaxLength = value;}
		}

		[Category("Behavior")]
		public char PasswordChar
		{
			get {return mpTextBox.PasswordChar;}
			set {mpTextBox.PasswordChar = value;}
		}

		[Category("Behavior")]
		public System.Windows.Forms.CharacterCasing CharacterCasing
		{
			get {return mpTextBox.CharacterCasing;}
			set {mpTextBox.CharacterCasing = value;}
		}

		[Category("Behavior")]
		public bool HideSelection
		{
			get {return mpTextBox.HideSelection;}
			set {mpTextBox.HideSelection = value;}
		}

		[Browsable(true),
		Bindable(true),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
		Category("Appearance")]
		public override string Text
		{
			get {
                return mpTextBox.Text;
            }
			set
			{
				mpTextBox.Text = value;
			}
		}


		[Category("Appearance")]
		public HorizontalAlignment TextAlign
		{
			get {return mpTextBox.TextAlign;}
			set {mpTextBox.TextAlign = value;}
		}

		public new Size Size
		{
			get {return base.Size;}

			set
			{
				if(value.Height > mpTextBox.Height + 1)
				{					
					base.Size = value;

					int yPos = (value.Height - mpTextBox.Height) / 2;
					mpTextBox.Top = yPos;					
				}				
			}
		}

		[Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public bool IsModified
		{
			get {return mpTextBox.Modified;}
			set {mpTextBox.Modified = value;}
		}

		#endregion

		#region IFlashabledControl

		public void FlashControl()
		{
			Thread m_Thread = new Thread(new ThreadStart(ThreadFlashControl));
			m_Thread.Start();
		}
		
		#endregion
	}
}
